import com.mongodb.MongoClient;
import com.mongodb.client.*;
import org.bson.Document;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Export {

    Properties properties;
    private MongoConnClient mongoConnClient;


    public static void main(String[] args) {

        Export export =new Export();
        List<String> resultContent = new ArrayList<>();
        List<String> resultIndex = new ArrayList<>();
        //加载配置文件
        export.loadProperty();

        //读取mongodb配置
        String mongoDB_uri = export.getParameter("MongoDB_URI");
        String outPut_dBs = export.getParameter("OutPut_DBs");
        //读取导出文件的路径
        String outPut_indexFile = export.getParameter("OutPut_IndexFile");
        String outPut_file = export.getParameter("OutPut_File");

        Set<String> outDBNames = new HashSet<>();
        if(outPut_dBs!=null&&outPut_dBs.trim().length()>0){
            String[] split = outPut_dBs.split(",");
            for (String s : split) {
                outDBNames.add(s);
            }
        }
        //连接mongodb数据库
        export.mongodbConnect(mongoDB_uri);
        MongoClient mongoClient = export.getMongoClient();
        MongoIterable<String> databaseNames = mongoClient.listDatabaseNames();
        for (String dbName:databaseNames) {
            if(dbName.equals("admin")||dbName.equals("local")||dbName.equals("config")){
                continue;
            }
            if(outDBNames.size()>0&&!outDBNames.contains(dbName)){//配置了输出库名，并且不此库名不在这个集合中，则不输出
                continue;
            }
            resultContent.add("use ".concat(dbName).concat(";"));
            resultIndex.add("use ".concat(dbName));
            MongoDatabase database = mongoClient.getDatabase(dbName);
            MongoIterable<String> collectionNames = database.listCollectionNames();
            for (String collectionName : collectionNames) {
                MongoCollection<Document> dbCollection =  database.getCollection(collectionName);

                //集合
                if(outPut_file== null || outPut_file.trim().length()==0){//不导出
                    continue;
                }
                FindIterable<Document> outResult = dbCollection.find().sort(new Document("$natural",-1));
                MongoCursor<Document> cursor = outResult.iterator();
                Document docResult = null;
                try {
                    while(cursor.hasNext()){
                        docResult = cursor.next();
                        docResult.remove("_id");
                        String json = docResult.toJson();
                        StringBuilder sb = new StringBuilder();
                        sb.append("db.");
                        sb.append(collectionName);
                        sb.append(".insert(");
                        sb.append(json);
                        sb.append(");");
                        resultContent.add(sb.toString());

//                        Set<String> fieldNames = docResult.keySet();
//                        for (String fieldName:fieldNames) {
//                            Object fieldValue = docResult.get(fieldName);
//                            System.out.println("fieldName:"+fieldName+",fieldValue:"+fieldValue);
//                        }
                        break;
                    }

                } catch (Exception e) {

                    e.printStackTrace();
                }finally{
                    if(cursor!=null)
                    {
                        cursor.close();
                    }
                }



                //索引
                //db.UserInfo.createIndex({"UserName":1},{"name":'idx_UserName',background:true})
                //db.UserInfo4.createIndex({"UserName":1,"Interest.InterestId":1},{"name":'idx_UserName',background:true,unique:true})

                //Document{{v=2, key=Document{{_id=1}}, name=_id_, ns=User.UserInfo}}
                //Document{{v=2, key=Document{{UserName=1.0}}, name=idx_UserName, ns=User.UserInfo, background=true}}
                //Document{{v=2, unique=true, key=Document{{UserName=1.0}}, name=idx_UserName, ns=User.UserInfo2, background=true}}
                //Document{{v=2, unique=true, key=Document{{UserName=1.0, Interest.InterestId=1.0}}, name=idx_UserName, ns=User.UserInfo4, background=true}}

                if(outPut_indexFile== null || outPut_indexFile.trim().length()==0){//不导出创建索引文件的命令
                    continue;
                }
                try {
                    ListIndexesIterable<Document> documentIndexes = dbCollection.listIndexes();
                    for (Document documentIndex : documentIndexes) {
                        if (documentIndex.getString("name").equals("_id_")) {//去掉默认索引
                            continue;
                        }
                        StringBuilder sbIndex = new StringBuilder();
                        Document document = (Document) (documentIndex.get("key"));

                        sbIndex.append("db.");
                        sbIndex.append(collectionName);
                        sbIndex.append(".createIndex(");
                        sbIndex.append(document.toJson());
                        sbIndex.append(",{");
                        sbIndex.append("'name':");
                        sbIndex.append("'"+documentIndex.getString("name")+"'");

                        if (documentIndex.containsKey("background")) {
                            sbIndex.append(",'background':");
                            sbIndex.append(documentIndex.getBoolean("background"));
                        }
                        if (documentIndex.containsKey("unique")) {
                            sbIndex.append(",'unique':");
                            sbIndex.append(documentIndex.getBoolean("unique"));
                        }
                        sbIndex.append("})");
                        resultIndex.add(sbIndex.toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

        //输出文件 outPut_file
        if(outPut_file!= null || outPut_file.trim().length()>0) {
            export.outPutFile(resultContent, outPut_file);
        }

        if(outPut_indexFile!= null || outPut_indexFile.trim().length()>0){
            export.outPutFile(resultIndex,outPut_indexFile);
        }

    }

    private void outPutFile(List<String> list,String outPut_File){
        Iterator<String> iterator = list.iterator();
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(outPut_File);//创建文本文件
            int i=0;
            while(list!=null&&iterator.hasNext()){//循环写入

                fileWriter.write(iterator.next()+"\r\n");//写入 \r\n换行
                i++;
            }
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void loadProperty() {
        properties = new Properties();
        InputStream inputStream = Object.class.getResourceAsStream("/config.properties");
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定参数，如果参数不存在，则返回""
     * @param strName 参数名称
     * @return 参数值
     */
    public String getParameter(String strName)
    {
        String strValue=properties.getProperty(strName);
        if(strValue==null)
        {//参数不存在
            return "";
        }

        return strValue;
    }

    /**
     * 获取指定参数，如果参数不存在，则返回指定的缺省值
     * @param strName 参数名称
     * @return 参数值
     */
    public String getParameter(String strName,String strDefaultValue)
    {
        String strValue=properties.getProperty(strName);
        if(strValue==null)
        {//参数不存在
            return strDefaultValue;
        }

        return strValue;
    }




    public boolean mongodbConnect(String mongodb_uri) {
        this.mongoConnClient.setMongoClientURI(mongodb_uri);
        return this.mongoConnClient.connect();
    }

    public MongoClient getMongoClient()
    {
        return this.mongoConnClient.getMongoClient();
    }

    public MongoDatabase getDatabaseDB(String strDBName)
    {
        return this.mongoConnClient.getDatabaseDB(strDBName);
    }

    public Export() {
        this.mongoConnClient =new MongoConnClient();
    }

}
